<?php

namespace app\api\model\xykeep\goods;

use think\Model;
use traits\model\SoftDelete;
use app\api\model\xykeep\User;
use app\api\model\xykeep\Goods as GoodsModel;
use app\api\model\xykeep\goods\OrderItem as OrderItemModel;
use app\api\model\xykeep\user\Address as UserAddressModel;
use app\api\model\xykeep\Cart;
use addons\xykeep\exception\Exception;
use app\api\model\xykeep\Config;
use fast\Http;
use think\Db;
use think\Queue;

class Order extends Model
{

    use SoftDelete;

    // 表名
    protected $name = 'xykeep_goods_order';

    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'integer';

    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $deleteTime = 'deletetime';

    // 追加属性
    protected $append = [
        'pay_type_text',
        'paytime_text',
        'platform_text',
        'status_text',
        'delivery_type_text',
        'ext_arr'
    ];

    public function getExtArrAttr($value, $data)
    {
        $ext = (isset($data['ext']) && $data['ext']) ? json_decode($data['ext'], true) : [];
        return $ext;
    }

    // 加载订单数据
    public static function getInitData($params,$init_type = '')
    {
        extract($params);

        $user = User::info();

        //配送方式
        $expressType = self::getExpressType();
        if(count($expressType) == 0){
            new Exception('系统未配置配送方式！');
        }

        // 检测并重新组装要购买的商品列表,返回商品列表和总价
        list($orderGoodsList,$goodsAmount,$totalNum) = self::checkGoods($goods_list);
        // 订单运费



//        // 1. 获取所有 goods_id
// 1. 获取所有 goods_id
        $goodsIds = array_column($orderGoodsList, 'goods_id');

// 2. 查询最大的 freight（ThinkPHP 5.1+）
        $deliveryAmount = GoodsModel::whereIn('id', $goodsIds)->max('freight') ?: 0;



        // 订单总金额，需支付金额
        $totalAmount = bcadd($goodsAmount, $deliveryAmount, 2);
        $couponFee = 0; //优惠券抵扣金额
        $totalFee = bcsub($totalAmount, $couponFee, 2);
        $totalFee = $totalFee < 0 ? 0 : $totalFee;

        //获取用户默认收货地址
        $userAddress = UserAddressModel::where(['user_id'=>$user->id,'is_default'=>1])->find();

        if($init_type == 'create' && !$userAddress){
            new Exception('请选择收货地址');
        }

//        $totalAmount = $totalFee = '0.00';

        return [
            'express_type' => $expressType,
            'order_goods_list' => $orderGoodsList, //商品列表
            'goods_amount' => $goodsAmount, //商品总价
            'delivery_amount' => $deliveryAmount, //订单运费
            'total_amount' => $totalAmount, //订单总金额
            'total_fee' => $totalFee, //支付金额
            'coupon_fee' => $couponFee, //优惠券抵扣金额
            'total_num' => $totalNum, //商品件数
            'user_address' => $userAddress, //收货地址
        ];
    }

    public static function getLogistics($params)
    {

        extract($params);
        $user = User::info();
        $order = self::where(['user_id'=>$user->id,'id'=>$id])->find();

        if($order['status'] < 2){
            new Exception('订单状态错误');
        }

        // 查询接口
        $qurl = "https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";

        $config = Config::getValueByName('shop');


        if($config['kdnid'] == '' || $config['kdnkey']==''){
            new Exception('系统未配置物流查询');
        }

        // 组装应用级参数
        $requestData= "{".
            "'CustomerName': '',".
            "'OrderCode': '',".
            "'ShipperCode': '".$order['delivery_company_code']."',".
            "'LogisticCode': '".$order['delivery_no']."',".
            "}";
        // 组装系统级参数
        $datas = array(
            'EBusinessID' => $config['kdnid'],
            'RequestType' => '8001',
            'RequestData' => urlencode($requestData) ,
            'DataType' => '2',
        );

        $datas['DataSign'] = urlencode(base64_encode(md5($requestData.$config['kdnkey']))); //encrypt($requestData, $apiKey);
        //以form表单形式提交post请求，post请求体中包含了应用级参数和系统级参数

        $result = Http::sendRequest($qurl, $datas, 'POST', []);


        if ($result['ret'] == 1) {
            $exResult = json_decode($result['msg'], true);

            if (!$exResult['Success']) {
                new Exception($exResult['Reason']);
            }


            return $exResult;

        } else {

            new Exception($result['msg'], '');
        }


    }

    //确认收货
    public static function takeDelivery($params)
    {

        extract($params);

        Db::startTrans();
        try{
            $user = User::info();
            $order = self::where(['user_id'=>$user->id,'id'=>$id])->find();

            if($order['status'] != 2){
                throw Exception('订单状态错误');
            }

            // 支付后监听
            $params = ['order'=>$order,'type'=>'goods'];
            \think\Hook::listen('xykeep_order_over_after', $params);

            $result = $order->save(['status'=>3,'take_delivery_time'=>time()]);
            Db::commit();
            return $result;
        } catch (\Exception $e) {
            Db::rollback();
            new Exception($e->getMessage());
        }

    }



    /**
     * 创建订单
     */
    public static function addOrder($params)
    {
        $user = User::info();
        extract($params);
        $order_type = $order_type ?? 'goods';

        $goods_ids = array_column($goods_list,'goods_id');
        $store_ids = Db::name('xykeep_goods')
            ->where(['id' => ['in', $goods_ids]])
            ->column('store_id');

        // 对店铺ID数组进行去重
        $store_ids = array_unique($store_ids);

        if (count($store_ids) > 1) {
            throw new \think\Exception('你不能同时下单两个店铺的商品');
        } else {
            $store_ids = $store_ids[0]; // 提取唯一店铺ID
        }

        // 订单数据
        extract(self::getInitData($params, "create"));
        $close_time = 15;//15分钟为支付自动关闭

        $order = Db::transaction(function () use (
            $user,
            $order_type,
            $goods_amount,
            $delivery_amount,
            $total_num,
            $total_amount,
            $total_fee,
            $coupon_fee,
            $order_goods_list,
            $user_address,
            $close_time,
            $from,
            $store_ids
        ) {

            $orderData = [];
            $orderData['order_sn'] = xykeepCreateOrderNo();
            $orderData['user_id'] = $user->id;
            $orderData['type'] = $order_type;
            $orderData['from'] = $from;
            $orderData['total_num'] = $total_num;
            $orderData['goods_amount'] = $goods_amount;
            $orderData['delivery_amount'] = $delivery_amount;
            $orderData['total_amount'] = $total_amount;
            $orderData['total_fee'] = $total_fee;
            $orderData['coupon_fee'] = $coupon_fee;
            $orderData['consignee'] = $user_address->consignee;
            $orderData['phone'] = $user_address->phone;
            $orderData['city'] = $user_address->city;
            $orderData['address'] = $user_address->address;
            $orderData['status'] = (float)$total_fee>0?0:1;//允许0元购，而直接算已支付
            $orderData['platform'] = request()->header('platform');
            $orderData['ext'] = json_encode(['expired_time' => time() + ($close_time * 60)]);
            $orderData['store_id'] = $store_ids;
            $order = new Order();
            $order->allowField(true)->save($orderData);

            // 添加订单选项
            foreach ($order_goods_list as $key => $buyinfo) {
                $detail = $buyinfo['detail'];
                $current_sku_price = $detail['current_sku_price'];

                $orderItem = new OrderItem();
                $orderItem->goods_order_id = $order->id;
                $orderItem->goods_id = $buyinfo['goods_id'];
                $orderItem->goods_sku_price_id = $buyinfo['sku_price_id'];
                $orderItem->goods_sku_text = $current_sku_price['goods_sku_text'];
                $orderItem->goods_title = $detail->title;
                $orderItem->goods_image = empty($current_sku_price['image']) ? $detail->image : $current_sku_price['image'];
                $orderItem->goods_price = $detail->current_sku_price->price;
                $orderItem->buy_num = $buyinfo['buy_num'] ?? 1;
                $orderItem->goods_weight = $detail->current_sku_price->weight;
                $orderItem->save();
            }

            return $order;
        });

        // 删除购物车
        if ($from == 'cart') {
            foreach ($order_goods_list as $delCart) {
                Cart::where([
                    'user_id' => $user->id,
                    'goods_id' => $delCart['goods_id'],
                    'sku_price_id' => $delCart['sku_price_id'],
                ])->delete();
            }
        }

        //订单关闭队列
        //Queue::later(($close_time * 60), '\addons\xykeep\job\Order@autoClose', ['order' => $order,'type'=>'goods'], 'XYkeep');

        return $order;
    }

    /**
     * 订单支付成功
     *
     * @param [type] $order
     * @param [type] $notify
     * @return void
     */
    public function paySuccess($order, $notify)
    {

        $order->status = 1;
        $order->paytime = time();
        $order->transaction_id = $notify['transaction_id'];
        $order->payment_json = $notify['payment_json'];
        $order->pay_type = $notify['pay_type'];
        $order->pay_fee = $notify['pay_fee'];
        $order->save();

        //更新商品销量
        $orderItem = OrderItemModel::where(['goods_order_id'=>$order['id']])->select();
        foreach($orderItem as $oi){
            $goods = (new GoodsModel)->where(['id'=>$oi['goods_id']])->find();
            $goods->setInc('sales',$oi['buy_num']);
        }


        // 支付后监听
        $params = ['order'=>$order,'type'=>'goods'];
        \think\Hook::listen('xykeep_order_payed_after', $params);

        return $order;
    }


    /**
     * 获取发货方式
     */

    public static function getExpressType()
    {

        $config = Config::getValueByName('shop')['express_type'];

        $expressType = [];
        if(in_array('express',$config)){
            $expressType[] = ['name'=>'快递发货','value'=>'express'];
        }
        if(in_array('storetake',$config)){
            $expressType[] = ['name'=>'门店自提','value'=>'storetake'];
        }
        return $expressType;
    }

    // 取消订单
    public static function cancelOrder($params)
    {
        $user = User::info();
        extract($params);
        $order = self::where(['user_id'=>$user->id,'id'=>$id,'status'=>0])->find($id);
        if (!$order) {
            new Exception('订单不存在或已取消');
        }
        $order->status = -1;        // 取消订单
        $order->ext = json_encode($order->setExt($order, ['cancel_time' => time()]));      // 取消时间
        $order->save();
        return $order;
    }


    // 下单前检测，商品状态、库存
    public static function checkGoods($goods_list)
    {

        $orderGoodsList = [];
        $goodsAmount = 0;
        $totalNum = 0;
        foreach ($goods_list as $k => $buyinfo) {
            // 最少购买一件
            $buyinfo['buy_num'] = intval($buyinfo['buy_num']) < 1 ? 1 : intval($buyinfo['buy_num']);

            $sku_price_id = $buyinfo['sku_price_id'];

            $detail = GoodsModel::getDetail($buyinfo['goods_id']);

            $sku_prices = $detail['sku_price'];
            foreach ($sku_prices as $k => $sku_price) {
                if ($sku_price['id'] == $sku_price_id) {
                    $detail->current_sku_price = $sku_price;
                    break;
                }
            }

            if (!$detail || $detail->status == 'down') {
                new Exception('商品不存在或已下架');
            }

            if (!isset($detail->current_sku_price) || !$detail->current_sku_price) {
                new Exception('商品规格不存在');
            }

            //商品详情
            $buyinfo['detail'] = $detail;
            $orderGoodsList[] = $buyinfo;

            // 当前库存，小于要购买的数量
            if ($detail->current_sku_price['stock'] < $buyinfo['buy_num']) {
                new Exception($detail['title'].'商品库存不足');
            }

            // 当前商品总价
            $currentAmount = bcmul($detail->current_sku_price->price, $buyinfo['buy_num'], 2);
            $goodsAmount = bcadd($goodsAmount, $currentAmount, 2);

            // 商品件数
            $totalNum = $totalNum + $buyinfo['buy_num'];
        }

        if (!count($orderGoodsList)) {
            new Exception('请选择要购买的商品');
        }

        return [$orderGoodsList,$goodsAmount,$totalNum];
    }

    // 订单详情
    public static function getDetail($params)
    {
        $user = User::info();
        extract($params);

        $order = self::with(['item']);
//        $order->where('user_id', $user->id);//限制用户查询，但是现在添加了商家的功能，所以商家也可以查询，所以注释起来

        if (isset($order_sn)) {
            $order = $order->where('order_sn', $order_sn);
        }
        if (isset($id)) {
            $order = $order->where('id', $id);
        }

        $order = $order->find();

        if (!$order) {
            new Exception('订单不存在');
        }

        $order->append(['store']);

        return $order;
    }

    public static function getLists($params)
    {
        extract($params);
        $user = User::info();
        $where = ['user_id'=>$user->id];
        if($status != 'all'){
            //3（评价前）和5同时（评价后）字面意思上都可以代表一万次
            if($status=='3' || $status=='5'){
                $where['status'] = ['in','3,5'];
            }else{
                $where['status'] = $status;
            }
        }
        $list = self::with(['item'])->where($where)->order('id desc')->paginate();

        $list->each(function ($item) {
           $item->append(['store']);
        });

        return $list;
    }

    public function setExt($order, $field, $origin = [])
    {
        $newExt = array_merge($origin, $field);

        $orderExt = $order['ext_arr'];

        return array_merge($orderExt, $newExt);
    }

    public function getPayTypeList()
    {
        return ['wechat' => __('Wechat')];
    }

    public function getPlatformList()
    {
        return ['wxMiniProgram' => __('Wxminiprogram')];
    }

    public function getStatusList()
    {
        return [
            '-2' => __('Goods Status -2'),
            '-1' => __('Goods Status -1'),
            '0' => __('Goods Status 0'),
            '1' => __('Goods Status 1'),
            '2' => __('Goods Status 2'),
            '3' => __('Goods Status 3'),
            '4' => __('Goods Status 4'),
            '5' => __('Goods Status 5')
        ];
    }

    public function getStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
        $list = $this->getStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    public function getDeliveryTypeList()
    {
        return ['express' => __('物流快递'), 'storetake' => __('门店自提')];
    }

    public function getDeliveryTypeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['delivery_type']) ? $data['delivery_type'] : '');
        $list = $this->getDeliveryTypeList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    public function getPayTypeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['pay_type']) ? $data['pay_type'] : '');
        $list = $this->getPayTypeList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public function getPaytimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['paytime']) ? $data['paytime'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }


    public function getPlatformTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['platform']) ? $data['platform'] : '');
        $list = $this->getPlatformList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    protected function setPaytimeAttr($value)
    {
        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
    }

    public function item()
    {
        return $this->hasMany(OrderItem::class, 'goods_order_id', 'id');
    }

    public function store()
    {
        return $this->belongsTo('app\common\model\Store', 'store_id', 'id', [], 'LEFT')->setEagerlyType(0);
    }

}
